﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BFlatCompile.Nodes;

namespace BFlatCompile.Serializer
{
	public class InlineValueSerializer
	{
		public static string Serialize(Compiler compiler)
		{
			Variable.Table.SortByFrequency();
			NumericalConstant.SortTables();
			StringConstant.SortTable();

			string stringTable = SerializeStringTable(compiler);
			string integerTable = SerializeIntegerTable(compiler);
			string floatTable = SerializeFloatTable(compiler);
			string idTable = SerializeIdTable(compiler);
			return stringTable + integerTable + floatTable + idTable;
		}

		public static string SerializeIdTable(Compiler compiler)
		{
			List<string> output = new List<string>();
			Variable.Table.SortByFrequency();
			string[] ids = Variable.Table.GetIds();
			bool readable = compiler.IsReadable;

			for (int i = 0; i < ids.Length; ++i)
			{
				output.Add(readable ? (i + ": " + ids[i]) : ids[i]);
			}

			return string.Join(readable ? "\n" : "|", output);
		}

		public static string SerializeIntegerTable(Compiler compiler)
		{
			List<string> output = new List<string>();
			bool readable = compiler.IsReadable;
			NumericalConstant.SortTables();
			int[] integers = NumericalConstant.GetIntegerTable();
			for (int i = 0; i < integers.Length; ++i)
			{
				output.Add(readable ? (i + ": " + integers[i]) : Util.ToHex(compiler, integers[i]));
			}

			return string.Join(readable ? "\n" : "|", output);
		}

		private static readonly System.Globalization.CultureInfo cultureInfo = new System.Globalization.CultureInfo("en-US");

		public static string SerializeFloatTable(Compiler compiler)
		{
			bool readable = compiler.IsReadable;
			List<string> output = new List<string>();
			string[] floats = NumericalConstant.GetFloatTable();
			for (int i = 0; i < floats.Length; ++i)
			{
				string actualEntry = "0";
				double value = double.Parse(floats[i]);
				if (value != 0)
				{
					actualEntry = value.ToString("E", cultureInfo);
				}

				if (readable)
				{
					output.Add((i) + ": " + floats[i] + ", " + actualEntry);
				}
				else
				{
					output.Add(actualEntry);
				}
			}

			return string.Join(readable ? "\n" : "|", output);
		}

		public static string SerializeStringTable(Compiler compiler)
		{
			List<string> output = new List<string>();
			bool readable = compiler.IsReadable;

			int i = 0;
			foreach (string entry in StringConstant.GetStringTable())
			{
				output.Add(readable ? ((i++) + ": " + entry) : Util.ConvertStringToHex(compiler, entry));
			}

			return string.Join(readable ? "\n" : "|", output);
		}

	}
}
